﻿using ErrorOr;
using Gnivc.CarDealership.Api.Application.Abstractions.Repositories;
using Gnivc.CarDealership.Api.Domain.Entities;
using Gnivc.CarDealership.Api.Infrastructure.Persistence;
using Microsoft.EntityFrameworkCore;

namespace Gnivc.CarDealership.Api.Infrastructure.Repositories;

public class ReservationRepository : IReservationRepository
{
    private readonly IApplicationDbContext _context;

    public ReservationRepository(IApplicationDbContext context)
    {
        _context = context;
    }

    public async Task<ErrorOr<IEnumerable<Reservation>>> GetAllByVehicle(Guid vehicleId)
    {
        return await _context.Reservations
            .AsNoTracking()
            .Include(r => r.User)
            .Where(r => r.VehicleId == vehicleId && !r.IsDeleted)
            .OrderByDescending(r => r.StartDate)
            .ToListAsync();
    }

    public async Task<ErrorOr<Reservation?>> GetByIdAsync(Guid reservationId)
    {
        var reservation = await _context.Reservations
            .Where(b => b.Id == reservationId && !b.IsDeleted)
            .SingleOrDefaultAsync();

        if (reservation == null)
            return Error.NotFound();

        return reservation;
    }

    public async Task<ErrorOr<Created>> AddAsync(Reservation reservation)
    {
        await _context.Reservations.AddAsync(reservation);
        var result = await _context.SaveChangesAsync();

        if (result < 1)
            return Error.Unexpected();

        return new Created();
    }

    public async Task<ErrorOr<Updated>> UpdateAsync(Reservation reservation)
    {
        _context.Reservations.Update(reservation);
        var result = await _context.SaveChangesAsync();

        if (result < 1)
            return Error.Unexpected();

        return new Updated();
    }

    public async Task ReservationCleanup(CancellationToken cancellationToken)
    {
        var now = DateTime.UtcNow;

        var expiredReservations = _context.Reservations
            .Where(r => !r.IsDeleted && r.EndDate < now)
            .ToList();

        foreach (var reservation in expiredReservations)
            reservation.IsDeleted = true;

        _context.Reservations.UpdateRange(expiredReservations);
        await _context.SaveChangesAsync(cancellationToken);
    }
}
